﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using CefSharp.WinForms;
using CefSharp;
using Linphone;
using WindowsFormsLinphoneV.com.amall.common;
using VSHT.com.amall.controller;
using Firearms;
using VienApi;
using Sunny.UI;
using VSHT.sdk;
using System.Threading;
using Timer = System.Windows.Forms.Timer;
using Firearms.dal;

namespace VSHT
{
    public partial class Form1 : Form
    {
        // 定义一个静态的 ChromiumWebBrowser 实例，用于显示网页内容
        public static ChromiumWebBrowser browser;
        // 当前浏览器显示的网页地址
        string curAddress = "";
        // 控制数据操作的数据控制器实例
        public DataController dataController;

        internal static MyLinPhone myPhone;
        public static videoForm videoForm;
        private VienApiHelper apiHelper = new VienApiHelper(new PictureBox());
        internal ApiResult varret;
         private Timer timer;
        public static string fingerType;
        public Form1()
        {
            if (dataController == null)
            {
                dataController = new DataController();
                dataController.Form1 = this;
            }
            this.FormClosing += Form1_FormClosing;
            InitializeComponent();
            InitBrowser();
            ViodeWin();
        }
       

        private void Form1_Load(object sender, EventArgs e)
        {
            // 检查指纹或设备类型
            checkFingerDevice();
            // 获取默认的网页地址配置
            var url = Utils.initSystemConfig().default_url;

            // 如果网页地址不是以 "http" 开头，则使用本地资源路径作为默认地址
            if (!url.StartsWith("http"))
            {
                url = Application.StartupPath + @"/resource/index.html";
            }
            // 调用 loadUrl 方法加载指定的网页地址
            loadUrl(url);
            
            apiHelper.PropertyChanged += ApiHelper_PropertyChanged;
           
            this.Resize += Form1_Resize;
            /*   timer = new Timer();
               timer.Interval = 1000; // 每隔 1 秒执行一次
               timer.Tick += Timer_Tick;
               timer.Start();*/
            videoForm = new videoForm();

        }

        private void checkFingerDevice()
        {
            openret = ZAZApi.openDeviceEx(ref dev, 4, 0, 0, 0, 0);
            if(openret == 0)
            {
                fingerType = "za";
                ZAZApi.closeDeviceEx(Handle, naddr);
            }

        }

        //指静脉停止采集
        internal bool fingerEnd()
        {
            if (Utils.initSystemConfig().fvdev_show == "true")
            {
                apiHelper.vienShow = false;
                return true;
            }
            else
            {
                return false;
            }
            
        }
        //指静脉开启定时器
        private void Timer_Tick(object sender, EventArgs e)
        {
            // 调用验证方法
            varret = apiHelper.Open(browser);
            Console.WriteLine(varret);
            // 检查 varret.code 是否为 0，如果是则结束定时器
            if (varret.Code == 0)
            {
                // 停止定时器
                timer.Stop();
            }
        }

        private void Form1_Resize(object sender, EventArgs e)
        {
            // 窗体大小改变时，重新居中按钮
        }
        //通知web
        private void ApiHelper_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            Console.WriteLine(e.PropertyName, "调用方法");
            string javascriptCode = $"this.showMessage('{e.PropertyName}')";
            browser.GetMainFrame().ExecuteJavaScriptAsync(javascriptCode);
        }
        private void MyPhone_PropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            Console.WriteLine(e.PropertyName, "调用方法");
            string javascriptCode = $"this.PhoneMessage('{e.PropertyName}')";
            browser.GetMainFrame().ExecuteJavaScriptAsync(javascriptCode);
            if (e.PropertyName == "Call released")
            {
                Program.MainForm.Invoke(new Action(() =>
                {
                    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
                    //，窗体将不再可见，但仍然存在于内存中
                    videoForm.Hide();
                }));
            }
            else if (e.PropertyName == "Incoming CallSession")
            {
                Program.MainForm.Invoke(new Action(() =>
                {
                    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
                    videoForm.BringToFront();
                    videoForm.Show();
                    videoForm.BringToFront();
                   
                }));
            }
        }
        //当窗体关闭时，确保在关闭前停止浏览器。
        private  void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            // 检查是否存在正在使用的电话实例
            if (myPhone != null)
            {
                // 关闭电话连接
                myPhone.close();
                myPhone = null; // 将电话实例设为 null，以便在下次使用前重新初始化
            }
 
            apiHelper.Close();

           
        }

        public void endcx()
        {
            if (InvokeRequired)
            {
                Invoke(new Action(endcx));
                return;
            }

            // 关闭窗口
            this.Close();

            // 退出应用程序
            Application.Exit();
        }
        /// <summary>
        /// 加载指定的网页地址到 ChromiumWebBrowser 控件。
        /// </summary>
        /// <param name="url">要加载的网页地址。</param>
        public static void loadUrl(string url)
        {
            browser.LoadUrl(url);

        }

        /// <summary>
        /// 初始化浏览器控件，将 ChromiumWebBrowser 实例添加到窗体中。
        /// 设置事件处理和 JavaScript 交互配置。
        /// </summary>
        public void InitBrowser()
        {
          
            // 创建一个新的 ChromiumWebBrowser 实例，并设置默认初始地址为空字符串
            browser = new ChromiumWebBrowser("");
            browser.MenuHandler = new CustomContextHandler();
            // 将浏览器控件添加到当前窗体的控件集合中
            this.Controls.Add(browser);

            // 为 FrameLoadEnd 事件绑定 OpenDev 方法，用于在页面加载完成后执行特定操作
            browser.FrameLoadEnd += OpenDev;

            // 设置浏览器控件的填充方式，使其充满整个窗体区域
            browser.Dock = DockStyle.Fill;

            // 为 AddressChanged 事件绑定 Browser_AddressChanged 方法，用于监控地址栏地址的变化
            browser.AddressChanged += Browser_AddressChanged;

            // 启用传统绑定模式，以支持 JavaScript 与 C# 的交互
            browser.JavascriptObjectRepository.Settings.LegacyBindingEnabled = true;

            // 注册一个名为 "JsObject" 的 JavaScript 对象，并将其与 dataController 关联
            // 允许 JavaScript 通过 "JsObject" 来访问和调用 dataController 的方法和属性
            browser.JavascriptObjectRepository.Register("JsObject", dataController, isAsync: false, options: BindingOptions.DefaultBinder);
            // 使用 SendToBack 方法将 browser 控件置于底层
           

            Console.WriteLine(browser.Size);
        }
        public class CustomContextHandler : IContextMenuHandler
        {

            public void OnBeforeContextMenu(IWebBrowser chromiumWebBrowser, IBrowser browser, CefSharp.IFrame frame, IContextMenuParams parameters, IMenuModel model)
            {
                model.Clear();
            }


            public bool OnContextMenuCommand(IWebBrowser chromiumWebBrowser, IBrowser browser, CefSharp.IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags)
            {
                return false;
            }

            public void OnContextMenuDismissed(IWebBrowser chromiumWebBrowser, IBrowser browser, CefSharp.IFrame frame)
            {
                
            }

            public bool RunContextMenu(IWebBrowser chromiumWebBrowser, IBrowser browser, CefSharp.IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback)
            {
                return false;
            }
        }
        public void sent() {
           
        }
        /// <summary>
        /// 打开开发者工具，用于调试网页内容。
        /// 如果系统配置为调试模式，则显示 ChromiumWebBrowser 控件的开发者工具面板。
        /// </summary>
        /// <param name="sender">事件发送者</param>
        /// <param name="e">事件参数</param>
        public void OpenDev(object sender, EventArgs e)
        {
            bool isdebug = Utils.initSystemConfig().is_debug == "true" ? true : false;
            if (isdebug)
            {
                browser.ShowDevTools();
            }
        }


        /// <summary>
        /// 当浏览器地址发生变化时，更新当前地址信息。
        /// </summary>
        /// <param name="sender">事件发送者</param>
        /// <param name="e">事件参数</param>
        private void Browser_AddressChanged(object sender, AddressChangedEventArgs e)
        {
            // 更新当前地址信息
            curAddress = e.Address;
        }
        /// <summary>
        /// 创建视频窗口及相关按钮。
        /// </summary>
        public void ViodeWin()
        {
          

          

        }

      
        // 注册音视频操作
        internal void Reg(string callId, string callIp)
        {
            // 设置 SIP 服务器主机地址、用户名和密码
            String host = callIp + ":5060";
            String username = callId;
            String password = "123456";
            // 隐藏视频窗口（如果可见）
            // 创建电话实例，并进行注册操作
            if(myPhone == null)
            {
                Program.MainForm.Invoke(new Action(() =>
                {
                    myPhone = new MyLinPhone(videoForm.pictureBox1, host, username, password, videoForm.uiAvatar1, videoForm.uiAvatar2);
                }));
                myPhone.PropertyChanged += MyPhone_PropertyChanged;
                myPhone.Reg(username);
            }
            else
            {
                //myPhone.Reg(username);
            }
            
        }
        /// <summary>
        /// 结束通话的按钮点击事件处理方法。
        /// </summary>
        /// <param name="sender">事件的发送者。</param>
        /// <param name="e">事件参数。</param>
        internal void endCall()
        {
            if (myPhone != null)
            {
                try
                {
                    myPhone.callstop(); // 调用MyLinPhone类中的callstop方法结束通话。
                }
                catch (Exception ee)
                {
                    MessageBox.Show(ee.ToString()); // 显示异常信息，如果发生错误。
                }
            }
            else
            {
                MessageBox.Show("未初始化，请先执行初始化"); // 提示未初始化。
            }
        }

        /// <summary>
        /// 接听电话的按钮点击事件处理方法。
        /// </summary>
        /// <param name="sender">事件的发送者。</param>
        /// <param name="e">事件参数。</param>
        internal void acceptCall()
        {
            if (myPhone != null)
            {
                myPhone.callaccept(); // 调用MyLinPhone类中的callaccept方法接听电话。
            }
            else
            {
                MessageBox.Show("未初始化，请先执行初始化"); // 提示未初始化。
            }
        }

        //拨打音视频
        internal void callDevice(string usernanme)
        {
           
            try
            {
                if (myPhone == null)
                {
                    MessageBox.Show("未初始化，请先执行初始化");
                    return;
                }
                Program.MainForm.Invoke(new Action(() =>
                {
                    Console.WriteLine(Thread.CurrentThread.ManagedThreadId);
                    videoForm.Show();
                   
                    videoForm.BringToFront();

                }));
                String tUser = usernanme;
                myPhone.callto(tUser);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

        }

        //开始指静脉采集
        public void fingerVein(string id)
        {
            apiHelper.CreateTemplate(id);
        }
        //开始指静脉验证
        internal ApiResult ValidateVein()
        {
            if (Utils.initSystemConfig().fvdev_show == "true")
            {
                if(apiHelper.fvdev_get(0) > 0)
                {
                    return apiHelper.ValidateVein();
                }
                else
                {
                    return new ApiResult { Code = -2, Message = "请配置指静脉设备" };
                }
                
            }
            else
            {
                return new ApiResult { Code = -11, Message = "请配置指静脉设备" };
            }
        }
        //查询指静脉设备数量
        internal bool fingerShow()
        {
            return apiHelper.fvdev_get(0) > 0;

        }
        //删除指静脉
        internal uint delFvuser(uint ifv)
        {
            return apiHelper.delFvuser(ifv); ;
        }

        public static IntPtr dev = new IntPtr(2121);
        public static UInt32 naddr = 0xffffffff;
        public static int openret = 0;
        //打开指纹设备
        public Boolean open_fingerprint()
        {
            openret = ZAZApi.openDeviceEx(ref dev, 4, 0, 0, 0, 0);
           
            if(openret != 0)
            {
                Console.WriteLine("打开设备失败");
                return false;
            }
            else
            {
                int ret1 = ZAZApi.initConnnect(dev, naddr);
                if (ret1 != 0)
                {
                    Console.WriteLine("设备初始化失败");
                    return false;
                }
            }
           
            return true;
        }

        //中断
        public void StopRecordFingerPrint()
        {
            // th.Abort();
            if (ThreadType == 0) { return; }
            ThreadType = 0;
            isRunning = false; // 设置isRunning为false以终止线程
            th.Join(); // 等待线程结束
        }
        //读取SN码
        public int getSN()
        {
            if (openret != 0) { return 1; }
            int[] SNstr = new int[1];
            int ret = ZAZApi.getSN(dev, naddr, SNstr);
            if (ret == 0)
            {
                Console.WriteLine("读取SN号成功,SN:"+ SNstr[0]);
                return SNstr[0];
            }
            return 1;
        }
        public static int ThreadType = 0;
        public static bool isRunning;
        public static Thread th;
        public void ManageThread(int type)
        {
            ThreadType = type;
            isRunning = true;
            th = new Thread(() =>
            {
                while (isRunning)
                {
                    switch (ThreadType)
                    {
                        case 0:
                            break;
                        case 1:
                            Console.WriteLine("触发验证");
                            VertifyThread();
                            break;
                        case 2:
                            Console.WriteLine("触发录入");
                            RecordThread();
                            break;
                    }
                }
            });
            th.Start();
        }
        public unsafe void RecordThread()
        {
            int genCount = 3;
            int enRollStep = 0;
            int lastStep = 5;   
            int r;
            string data = "0";
            string starus ="1";
            //初始化连接
            string javascriptCode = $"this.setFing('{data}')";
            while (enRollStep < genCount)
            {
                if (ThreadType == 0) {  break; };
                //感应手指是否在指纹器
                r = ZAZApi.fingerDetect(dev, naddr);
                if (r == 2)
                {
                    //通知按下手指
                    if (lastStep != enRollStep)
                    {
                        lastStep = enRollStep;//下一个循环，还没有放手指
                        Console.WriteLine("通知按下手指" + enRollStep);
                        data = "0,0,"+enRollStep;
                        if(enRollStep == 0)
                        {
                            javascriptCode = $"this.setFing('{data}')";
                            browser.GetMainFrame().ExecuteJavaScriptAsync(javascriptCode);
                        }
                        

                        Thread.Sleep(1000);
                    }
                }
                if (r == 0)
                {
                    //获取特征图片
                    r = ZAZApi.getImage(dev, naddr);
                    if (r == 0)
                    {
                        //生成对应特征
                        r = ZAZApi.genChar(dev, naddr, enRollStep);
                        if (r == 0)
                        {
                            enRollStep++;
                            Console.WriteLine("按下手:" + enRollStep);
                             data = "0,0,"+enRollStep;
                            javascriptCode = $"this.setFing('{data}')";
                            browser.GetMainFrame().ExecuteJavaScriptAsync(javascriptCode);
                            //合并
                            if (enRollStep == 3)
                            {
                                r = ZAZApi.mergeChar(dev, naddr, 1, 3);
                                IntPtr emId = new IntPtr(0);
                                if (r == 0)
                                {
                                    r = ZAZApi.getEmptyId(dev, naddr, 1, 500, &emId);
                                    if (r == 0)
                                    {

                                        r = ZAZApi.storeChar(dev, naddr, 1, emId.ToInt32());
                                        var resstr = r == 0 ? "录入成功，ID：" + emId.ToString() : "失败";
                                        Console.WriteLine(resstr);
                                       if(r == 0)
                                        {
                                            starus = "200";
                                        }
                                        if (r == 24)
                                        {
                                            resstr = "指纹已注册";
                                            starus = "1";
                                            Console.WriteLine(resstr);
                                        }
                                        data =  starus + "," + emId.ToString() + "," + resstr  ;
                                        javascriptCode = $"this.setFing('{data}')";
                                        browser.GetMainFrame().ExecuteJavaScriptAsync(javascriptCode);
                                        ThreadType = 0;
                                        isRunning = false; // 设置isRunning为false以终止线程
                                        th.Join(); // 等待线程结束
                                                   //  loaddll.closeDeviceEx(dev, naddr);
                                       
                                        return;
                                    }
                                }
                                else
                                {
                                    //合并特征失败，返回
                                    ThreadType = 0;
                                    isRunning = false; // 设置isRunning为false以终止线程
                                    th.Join(); // 等待线程结束
                                    data =  "2" + "," + "0" + "," + "合并特征失败";

                                    javascriptCode = $"this.setFing('{data}')";
                                    browser.GetMainFrame().ExecuteJavaScriptAsync(javascriptCode);
                                    return;
                                }
                            }



                            //放开手指通知
                            while (true)
                            {
                                r = ZAZApi.fingerDetect(dev, naddr);

                                if (r == 0)
                                {
                                    if (lastStep != enRollStep)
                                    {
                                        lastStep = enRollStep;//下一个循环，还没有放手指
                                                              //通知放开手指
                                        Thread.Sleep(1000);
                                    }
                                }
                                if (r == 2)
                                {
                                    Thread.Sleep(1000);
                                    lastStep = 5;
                                    break;
                                }
                            }
                        }

                    }
                    if (r == 19)
                    {
                        ThreadType = 0;
                        isRunning = false; // 设置isRunning为false以终止线程
                        th.Join(); // 等待线程结束
                        data =  "3" + "," + "0" + "," + "指纹录入异常";
                        javascriptCode = $"this.setFing('{data}')";
                        browser.GetMainFrame().ExecuteJavaScriptAsync(javascriptCode);
                        return;

                    }
                }

            }
        }

        public Boolean delFing(int id ,int enId)
        {
            try
            {
                int start = id;
                int end = enId;
                int ret;
                ret = ZAZApi.delChar(dev, naddr, id, enId);
                if (ret == 0)
                {
                    Console.WriteLine("删除指纹成功");
                    return true;
                }
                else
                {
                    return false;
                }
            }
            catch
            {
                return false;
            }
           
                 
        }
        /// <summary>
        /// 指纹验证线程
        /// </summary>
        public unsafe void VertifyThread()
        {
            if (openret != 0) { return; }
            string data ;

            while (true)
            {
                int ret = 1;
                int r =0;
                IntPtr em = new IntPtr();
                r = ZAZApi.fingerDetect(dev, naddr);
                if (ThreadType == 0) { break; }
                if (r !=0){ continue; }
                int g = ZAZApi.getImage(dev, naddr);
              
                if (g == 0)
                {
                    g = ZAZApi.genChar(dev, naddr, 1);
                }
                if (g == 0)
                {
                    g = ZAZApi.search(dev, naddr, 1, 500, ret, &em);
                }
                if (g == 0)
                {
                    Console.WriteLine(g + em.ToString());
                    data = "{" + "status:0" + "," + "Id:" + em.ToString() + "," + "feature:" + "'指纹验证成'" + "}";
                    string javascriptCode = $"this.setFing({data})";
                    browser.GetMainFrame().ExecuteJavaScriptAsync(javascriptCode);
                    ThreadType = 0;
                    isRunning = false; // 设置isRunning为false以终止线程
                    th.Join(); // 等待线程结束
                    break;
                }
                if (g == 17)
                {
                    Console.WriteLine("指纹没有匹配");
                    data = "{" + "status:1" + "," + "Id:'null'"  + "," + "feature:" + "'指纹没有匹配'" + "}";
                    string javascriptCode = $"this.setFing({data})";
                    browser.GetMainFrame().ExecuteJavaScriptAsync(javascriptCode);
                    ThreadType = 0;
                    isRunning = false; // 设置isRunning为false以终止线程
                    th.Join(); // 等待线程结束
                    break;
                }
                var res = ZAZApi.err2str(g);
                Console.WriteLine(res + "!!!!!!!!!!!"+g);                                      
                byte[] ys = new byte[1024];
                var restr = System.Text.Encoding.Default.GetString(ys);
                //var restr = new String(res);
                //Thread.Sleep(5);//如果不延时，将占用CPU过高  
                
            }
           

        }

        //读取模板
        public unsafe void loadChar(int id)
        {
            var buffer = 1;
            int r = 1;
            int target = id;
            string data = "0";
            string javascriptCode = $"this.setFing('{data}')";
            byte[] res = new byte[498];
            IntPtr rlg = new IntPtr(0);
            r = ZAZApi.loadChar(dev, naddr, buffer, target);
            if (r != 0)
            {
                //  if (OpenFeeback) chromeBrowser.ExecuteScriptAsync("window.msg", new object[] { "不存在Id=" + target + "特征", "error", 3000 });
                //MessageBox.Show(showError(r));
                //data = new { status = "error", flag = false, Id = target, feature = "", msg = r };
               // data = "1" + "," + target + "," + r;
               // javascriptCode = $"this.setFing({data})";
               // browser.GetMainFrame().ExecuteJavaScriptAsync(javascriptCode);
                Console.WriteLine(data);
                //  return JsonConvert.SerializeObject(data);
            }
            else
            {
                // data = new { status = "error", flag = false, Id = target, feature = target, msg = r };
                data = "1" + "," + target + "," + r;
                 javascriptCode = $"this.setFing({data})";
                browser.GetMainFrame().ExecuteJavaScriptAsync(javascriptCode);
                Console.WriteLine(data);
            }
           
            r = ZAZApi.upChar(dev, naddr, buffer, res, &rlg);
            if (r != 0)
            {
                // if (OpenFeeback) chromeBrowser.ExecuteScriptAsync("window.msg", new object[] { "加载" + target + "特征异常", "error", 3000 });
                //MessageBox.Show(showError(r));
                data = "1" + "," + target + "," + r;
                javascriptCode = $"this.setFing({data})";
                browser.GetMainFrame().ExecuteJavaScriptAsync(javascriptCode);
                Console.WriteLine(data + "失败");
            }
            var result = HexAndByteArr.byteArr2hexString(res, rlg.ToInt32());
            // data = new { status = "success", flag = true, Id = target, feature = result };
            data = "400" + "," + target + "," + result;
            javascriptCode = $"this.setFing('{data}')";
            browser.GetMainFrame().ExecuteJavaScriptAsync(javascriptCode);
            Console.WriteLine(data);
        }
        //指纹同步
        public unsafe Boolean SetFingerPrintFeature(string val , int code)
        {
            Console.WriteLine( code + "同步成功"+val );
            int r;
                byte[] buffer = HexAndByteArr.hexString2byteArr(val);
                IntPtr blength = new IntPtr(498);
                //载入缓冲区
                r = ZAZApi.downChar(dev, naddr, 1, buffer, &blength);
                if (r == 0)
                {
                 r = ZAZApi.storeChar(dev, naddr, 1, code);
                
                }
                else
                {
                return false;
                }
            
           // if (OpenFeeback) chromeBrowser.ExecuteScriptAsync("window.msg", new object[] { string.Format("指纹同步信息：{0}，成功{1}，失败{2}", new object[] { totalCount.ToString(), successCount.ToString(), errorCount.ToString() }), "info", 3000 });
            return true;
        }

        public void zdh()
        {
            if (this.InvokeRequired)
            {
                this.Invoke((MethodInvoker)delegate { this.WindowState = FormWindowState.Maximized; });
            }
            else
            {
                this.WindowState = FormWindowState.Maximized;
            }
        }
        public void hy()
        {
            if (this.InvokeRequired)
            {
                this.Invoke((MethodInvoker)delegate { this.WindowState = FormWindowState.Normal; });
            }
            else
            {
                this.WindowState = FormWindowState.Normal;
            }
        }
        public void zxh()
        {
            if (this.InvokeRequired)
            {
                this.Invoke((MethodInvoker)delegate { this.WindowState = FormWindowState.Minimized; });
            }
            else
            {
                this.WindowState = FormWindowState.Minimized;
            }
        }
        public void gb()
        {
            if (this.InvokeRequired)
            {
                this.Invoke((MethodInvoker)delegate { this.Close(); });
            }
            else
            {
                this.Close();
            }
        }

    }
}
